; void combinar_asm (
; 	unsigned char *src_a,	edi
; 	unsigned char *src_b,	esi
; 	unsigned char *dst,	rdx
; 	int m,			rcx
; 	int n,			r8
; 	int row_size,		r9
; 	float alpha		xmm0
; );

global combinar_asm

section .data
	FLOAT_DIVISOR: dd 255.0

section .text

combinar_asm:
	push rbp
	mov rbp, rsp
	push rbx
	push r12
	push r13
	push r14
	push r15

	mov r10, 16	; r10: indice_col
	mov r11, 0 	; r11: indice fila

	divss xmm0, [FLOAT_DIVISOR]	; xmm0: 0000 0000 0000 ffff 
	shufps xmm0, xmm0, 0h		; xmm0: ffff ffff ffff ffff
	


proxima_fila:
misma_fila:
	sub r10, 16
	movdqu xmm1, [rdi + r10]
	movdqu xmm2, [rsi + r10]
	; procesar
	;psubusb xmm1, xmm2
	pxor xmm4, xmm4
	
	; SEGUNDO OPERANDO
	movdqu xmm3, xmm2
	; PARTE BAJA
	punpcklbw xmm3, xmm4	;xmm3: 0b0b 0b0b 0b0b 0b0b
	movdqu xmm5, xmm3
	punpcklwd xmm5, xmm4	;xmm5: 000b 000b 000b 000b
	cvtdq2ps xmm5, xmm5	;xmm5: ffff ffff ffff ffff
	mulps xmm5, xmm0
	cvtps2dq xmm5, xmm5	;xmm5: dddd dddd dddd dddd

	movdqu xmm6, xmm3	
	punpckhwd xmm6, xmm4
	cvtdq2ps xmm6, xmm6
	mulps xmm6, xmm0
	cvtps2dq xmm6, xmm6

	packssdw xmm5, xmm6

	; PARTE ALTA
	movdqu xmm3, xmm2
	punpckhbw xmm3, xmm4	;xmm3: 0b0b 0b0b 0b0b 0b0b
	movdqu xmm7, xmm3
	punpcklwd xmm7, xmm4	;xmm7: 000b 000b 000b 000b
	cvtdq2ps xmm7, xmm7	;xmm7: ffff ffff ffff ffff
	mulps xmm7, xmm0
	cvtps2dq xmm7, xmm7	;xmm7: dddd dddd dddd dddd

	movdqu xmm6, xmm3	
	punpckhwd xmm6, xmm4
	cvtdq2ps xmm6, xmm6
	mulps xmm6, xmm0
	cvtps2dq xmm6, xmm6

	packssdw xmm7, xmm6

	; MERGE
	packuswb xmm5, xmm7
	psubusb xmm2, xmm5	; xmm2: B - alpha * B / 255


	; PRIMER OPERANDO
	movdqu xmm3, xmm1
	; PARTE BAJA
	punpcklbw xmm3, xmm4	;xmm3: 0b0b 0b0b 0b0b 0b0b
	movdqu xmm5, xmm3
	punpcklwd xmm5, xmm4	;xmm5: 000b 000b 000b 000b
	cvtdq2ps xmm5, xmm5	;xmm5: ffff ffff ffff ffff
	mulps xmm5, xmm0
	cvtps2dq xmm5, xmm5	;xmm5: dddd dddd dddd dddd

	movdqu xmm6, xmm3	
	punpckhwd xmm6, xmm4
	cvtdq2ps xmm6, xmm6
	mulps xmm6, xmm0
	cvtps2dq xmm6, xmm6

	packssdw xmm5, xmm6

	; PARTE ALTA
	movdqu xmm3, xmm1
	punpckhbw xmm3, xmm4	;xmm3: 0b0b 0b0b 0b0b 0b0b
	movdqu xmm7, xmm3
	punpcklwd xmm7, xmm4	;xmm7: 000b 000b 000b 000b
	cvtdq2ps xmm7, xmm7	;xmm7: ffff ffff ffff ffff
	mulps xmm7, xmm0
	cvtps2dq xmm7, xmm7	;xmm7: dddd dddd dddd dddd

	movdqu xmm6, xmm3	
	punpckhwd xmm6, xmm4
	cvtdq2ps xmm6, xmm6
	mulps xmm6, xmm0
	cvtps2dq xmm6, xmm6

	packssdw xmm7, xmm6

	; MERGE
	packuswb xmm5, xmm7
	paddusb xmm5, xmm2	; xmm5: alpha * A / 255 + B - alpha * B / 255

	;guardo
	movdqu [rdx + r10], xmm5
	
	add r10, 32 	; me fijo si queda lugar para una iteracion completa
	cmp r10, r8
	jbe misma_fila
	
	; ver los bytes que faltan si faltan
	sub r10, 16
ultimos_bytes:
	cmp r10, r8
	jae preparo_proxima_fila
	
	;byte a byte
	xor eax, eax
	xor ebx, ebx
	mov al, [rdi + r10] 	; al: a
	mov bl, [rsi + r10]	; bl: b
	mov r12d, ebx		; r12b: b

	movd xmm3, eax
	cvtdq2ps xmm3, xmm3
	mulps xmm3, xmm0	; a * alpha/255
	cvtps2dq xmm3, xmm3
	movd eax, xmm3
	
	movd xmm6, ebx
	cvtdq2ps xmm6, xmm6
	mulps xmm6, xmm0	; b * alpha/255
	cvtps2dq xmm6, xmm6
	movd ebx, xmm6
	
	sub r12d, ebx		; b - b * alpha/255
	add r12d, eax		; b - b * alpha/255 + a * alpha/255
	mov [rdx + r10], r12b	
	inc r10
	jmp ultimos_bytes	

preparo_proxima_fila:
	add rdi, r9
	add rsi, r9
	add rdx, r9
	
	mov r10, 16
	inc r11
	cmp r11, rcx
	jb proxima_fila


	pop r15
	pop r14
	pop r13
	pop r12
	pop rbx
	pop rbp
	ret
